package abel.wlmr.model.unit;

import java.time.DateTimeException;

import abel.util.StdBcdNumber;
import abel.wlmr.model.WlmrBaseUnit;
import abel.wlmr.model.WlmrException;
import abel.wlmr.model.type.FlowPointC29Body;
import abel.wlmr.model.type.VolumeUnitField;
import io.netty.buffer.ByteBuf;

/**
 * B.5.11.2.4.70 F409：水表日冻结正向累积流量示值
 * 数据单元格式见表 B.170。
 * 表B.170 水表日冻结正向累积流量示值数据单元格式
 * 数据内容 数据格式 单位 字节数
 * 日冻结类数据时标 Td_d 见本附录 B.5.13.1.3.4 日月年 3
 * 终端抄表时间 见附录 C.15 分时日月年 5
 * 正向总流量示值 见附录 C.29 单位代号 5
 * 
 * @author Abel
 *
 */
public class AfnSecondF409Unit extends WlmrBaseUnit {
    private static final short FIXED_LENGTH = 3 + 5 + 5;

    /**
     * 日冻结类数据时标 Td_d 见本附录 B.5.13.1.3.4 日月年 3
     */
    private StdBcdNumber frozeTdd;

    /**
     * 终端抄表时间 见附录 C.15 分时日月年 5
     */
    private StdBcdNumber readingTime;

    /**
     * 正向总流量示值 见附录 C.29 单位代号 5
     */
    private FlowPointC29Body<VolumeUnitField> forwardFLow = new FlowPointC29Body<VolumeUnitField>(new VolumeUnitField());

    public AfnSecondF409Unit() {
        super();
    }

    public AfnSecondF409Unit(short guessedLen) {
        super(guessedLen);
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#appendBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        if (frozeTdd == null || frozeTdd.length() != 3) {
            throw new IllegalArgumentException("froze tdd should be 3 bcd long");
        }
        if (readingTime == null || readingTime.length() != 5) {
            throw new IllegalArgumentException("reading time should be 5 bcd long");
        }
        if (forwardFLow == null) {
            throw new IllegalArgumentException("forward flow can't be null");
        }

        buf.writeBytes(frozeTdd.toBytes());
        buf.writeBytes(readingTime.toBytes());
        forwardFLow.appendBuf(buf);

        return buf;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#parseBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        if (checkBuffer(buf) < 0) {
            return -1;
        }

        frozeTdd = new StdBcdNumber();
        frozeTdd.populateBytes(buf, 3);

        try {
            frozeTdd.toMeterC20Joda();
        } catch (DateTimeException e) {
            throw new WlmrException("invalid froze-tdd in C.20", e);
        }

        readingTime = new StdBcdNumber();
        readingTime.populateBytes(buf, 5);

        try {
            readingTime.toMeterC15Joda();
        } catch (DateTimeException e) {
            throw new WlmrException("invalid froze-tdd in C.15", e);
        }

        forwardFLow.parseBuf(buf);

        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.WlmrDataPart#getMinLength()
     */
    @Override
    public int getMinLength() {
        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#getFinalLen()
     */
    @Override
    public short getFinalLen() {
        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String.format("{frozeTdd:%s, readingTime:%s, forwardFLow:%s}", frozeTdd, readingTime, forwardFLow);
    }

    /**
     * 日冻结类数据时标 Td_d 见本附录 B.5.13.1.3.4 日月年 3
     * 
     * @return the frozeTdd
     */
    public StdBcdNumber getFrozeTdd() {
        return frozeTdd;
    }

    /**
     * 日冻结类数据时标 Td_d 见本附录 B.5.13.1.3.4 日月年 3
     * 
     * @param frozeTdd
     *            the frozeTdd to set
     */
    public void setFrozeTdd(StdBcdNumber frozeTdd) {
        if (frozeTdd == null || frozeTdd.length() != 3) {
            throw new IllegalArgumentException("froze tdd should be 3 bcd long");
        }

        this.frozeTdd = frozeTdd;
    }

    /**
     * 终端抄表时间 见附录 C.15 分时日月年 5
     * 
     * @return the readingTime
     */
    public StdBcdNumber getReadingTime() {
        return readingTime;
    }

    /**
     * 终端抄表时间 见附录 C.15 分时日月年 5
     * 
     * @param readingTime
     *            the readingTime to set
     */
    public void setReadingTime(StdBcdNumber readingTime) {
        if (readingTime == null || readingTime.length() != 5) {
            throw new IllegalArgumentException("reading time should be 5 bcd long");
        }

        this.readingTime = readingTime;
    }

    /**
     * 正向总流量示值 见附录 C.29 单位代号 5
     * 
     * @return the forwardFLow
     */
    public FlowPointC29Body<VolumeUnitField> getForwardFLow() {
        return forwardFLow;
    }

    /**
     * 正向总流量示值 见附录 C.29 单位代号 5
     * 
     * @param forwardFLow
     *            the forwardFLow to set
     */
    public void setForwardFLow(FlowPointC29Body<VolumeUnitField> forwardFLow) {
        if (forwardFLow == null) {
            throw new IllegalArgumentException("forward flow can't be null");
        }

        this.forwardFLow = forwardFLow;
    }
}
